import os
import string
import time
import win32api
import win32con


class Synthesizer:
    pai_time = 0
    file_data: str

    def __init__(self, file_name: str):
        """
            filename: file文件夹下文件的名字
            pai_time: 一拍的时间
        """
        self.file_name = file_name

    def countNum(self, index: int) -> int:
        """
        index: 左大括号的起始下标
        return: 大括号中的单元数

        """
        count = 0
        left_num = 1
        while left_num != 0:
            index += 1
            if left_num == 1:
                count += 1
            if self.file_data[index] in "([{":
                left_num += 1
                if left_num == 1:
                    count += 1
            elif self.file_data[index] in ")]}":
                left_num -= 1
        return count

    def check(self):
        """
        检查file_data的谱子是否合理
        """
        print("正在检查谱子...")
        if self.pai_time < 0:
            print("Error:每拍的时间小于0")
            exit()
        kuohao_stack = []
        dict1 = {'(': ')', '[': ']', '{': '}'}
        for char in self.file_data:
            print(char, end='')
            if char not in string.ascii_uppercase + '0([{)]} \n/':
                print(f"\n{char}不是标准规定的符号，不应出现！！！")
                exit()
            if char == '/' and kuohao_stack != []:
                print("\n最后这小部分括号匹配错误！！！")
                exit()
            if char == '\n' and kuohao_stack != []:
                print("\n最后这行括号匹配错误！！！")
                exit()
            if char in '([{':
                kuohao_stack.append(char)
            elif char in ')]}':
                if char == dict1[kuohao_stack[len(kuohao_stack) - 1]]:
                    del kuohao_stack[len(kuohao_stack) - 1]
                else:
                    print(f"\n最后的{char}未正确匹配")
                    exit()
        print("\n未检查出错误！")

    def login(self):
        """
        从文件中获取到数据给 pai_time 和 file_data
        """
        # 获取文件绝对路径
        file_path = "E:/QQ/聊天记录等数据/2983673271/FileRecv/" + self.file_name

        # 获取文件内容
        try:
            with open(file_path, "r", encoding="UTF-8") as f:
                self.pai_time = float(f.readline().strip())
                self.file_data = f.read()
        except FileNotFoundError:
            print("文件未找到")
        finally:
            if f:
                f.close()

        # 将小写字母转成大写，方便操作
        self.file_data = str.upper(self.file_data)

    def imitateKeyboardInput(self):
        """
        按照file_data模拟键盘输入
        """
        stop_time = self.pai_time
        is_stop = True
        num_list = []

        # 将文件内容按字母模拟输入
        for index in range(len(self.file_data)):
            char = self.file_data[index]
            if char in string.ascii_uppercase:  # 字符属于大写字母
                char_value = ord(char)
                win32api.keybd_event(char_value, 0, 0, 0)  # 按下
                win32api.keybd_event(char_value, 0, win32con.KEYEVENTF_KEYUP, 0)  # 松开
                if is_stop:
                    time.sleep(stop_time)
            elif char == '0':
                time.sleep(stop_time)
            elif char == '(':
                stop_time /= 2
            elif char == ')':
                stop_time *= 2
            elif char == '[':
                is_stop = False
            elif char == ']':
                is_stop = True
                time.sleep(stop_time)
            elif char == '{':
                num_list.append(self.countNum(index))
                stop_time /= num_list[len(num_list) - 1]
            elif char == '}':
                stop_time *= num_list[len(num_list) - 1]
                del num_list[len(num_list) - 1]

    def play(self):
        """
        调用各个功能
        """
        self.login()
        self.check()
        print("演奏还有5秒开始，请切到原神欣赏！")
        time.sleep(5)   # 睡眠5秒，用来切换
        self.imitateKeyboardInput()


if __name__ == '__main__':
    file_list = os.listdir("file")
    while True:
        for i in range(len(file_list)):
            print(i+1, file_list[i], sep=".")
        choose = eval(input("请输入你要弹的谱子的序号(退出程序输入0）:"))
        if choose == 0:
            exit()
        elif 1 <= choose <= len(file_list):
            choose_file_name = file_list[choose-1]
            break
        else:
            print("不存在该序号对应的文件，请重新输入！！！")
    Synthesizer(choose_file_name).play()
